﻿using Abp.Authorization;
using Abp.Events.Bus;
using Abp.IO.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Paas.App.Interface.Documents;
using Paas.App.Interface.Documents.Dtos;
using Paas.App.Interface.Documents.Messages;
using Paas.Core;
using Paas.Core.Const;
using Paas.Core.Const.Enums.Common;
using Paas.Core.Documents.Entities;
using Paas.Core.Documents.Events;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Basefr.App;
using Basefr.Core.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Paas.App.Documents
{
    [Route("Document")]
    [AbpAuthorize()]
    public class DocumentAppService : AppService, IDocumentAppService
    {
        private readonly IMainRepository<Document> _documentRepo;
        private readonly IMainRepository<DocumentFolder> _documentFolderRepo;
        private readonly IWebHostEnvironment _hostEnvironment;

        public DocumentAppService(IMainRepository<Document> documentRepo, IMainRepository<DocumentFolder> documentFolderRepo, IWebHostEnvironment hostEnvironment)
        {
            _documentRepo = documentRepo;
            _documentFolderRepo = documentFolderRepo;
            _hostEnvironment = hostEnvironment;
        }

        [HttpPost(nameof(SearchDocumentView))]
        public virtual SearchDocumentViewOutput SearchDocumentView(SearchDocumentViewInput input)
        {
            var userRoot = _documentFolderRepo.FirstOrDefault(p => p.Level == 0);

            if (userRoot == null)
            {
                _documentFolderRepo.InsertAndGetId(new DocumentFolder { ParentId = null, Name = "全部文件", Level = 0 });
            }

            var parent = _documentFolderRepo.FirstOrDefault(input.ParentId);
            if (parent == null)
            {
                throw new UserFriendlyException("当前目录无效");
            }

            return new SearchDocumentViewOutput();
        }

        [HttpPost(nameof(SearchDocumentByFolder))]
        public virtual SearchDocumentByFolderOutput SearchDocumentByFolder(SearchDocumentByFolderInput input)
        {
            var documents = _documentRepo.GetAll()
                .Include(p => p.Uploader)
                .Where(p => p.FolderId == input.FolderId)
                .OrderBy(p => p.Id)
                .ToList();

            return new SearchDocumentByFolderOutput { Items = ObjectMapper.Map<List<DocumentDto>>(documents) };
        }

        [HttpPost(nameof(UploadDocument))]
        [RequestSizeLimit(512 * 1024 * 1024)]
        public virtual UploadDocumentOutput UploadDocument([FromForm] EnumFileType fileType, [FromForm] int folderId, [FromForm] IFormFile file)
        {
            var folder = _documentFolderRepo.FirstOrDefault(folderId);

            if (folder == null)
            {
                throw new UserFriendlyException("目录无效");
            }

            var fileExt = file.FileName.Split('.').LastOrDefault();
            var physicalName = $"{Guid.NewGuid():N}.{fileExt ?? ""}";

            var documentEntity = new Document
            {
                Folder = folder,
                Name = file.FileName,
                Code = Guid.NewGuid().ToString("N"),
                PhysicalPath = physicalName,
                PhysicalName = physicalName,
                Size = file.Length,
                UploaderId = AbpSession.GetUserId()
            };

            var docId = _documentRepo.InsertAndGetId(documentEntity);

            documentEntity.PhysicalPath = Path.Combine(
                _hostEnvironment.ContentRootPath,
                SettingManager.GetSettingValue(SettingNames.DocumentUploadPath),
                //AbpSession.GetUserId().ToString(),
                documentEntity.CreationTime.ToString("yyy-MM-dd"));

            if (!Directory.Exists(documentEntity.PhysicalPath))
            {
                Directory.CreateDirectory(documentEntity.PhysicalPath);
            }

            documentEntity.PhysicalName = $"{docId}_{physicalName}";

            System.IO.File.WriteAllBytes(Path.Combine(documentEntity.PhysicalPath, documentEntity.PhysicalName), file.OpenReadStream().GetAllBytes());

            EventBus.Default.Trigger(new DocumentUploadEvent { Document = documentEntity });

            return new UploadDocumentOutput { Item = ObjectMapper.Map<DocumentDto>(documentEntity) };
        }

        [AbpAllowAnonymous]
        public virtual DownloadDocumentOutput DownloadDocument(DownloadDocumentInput input)
        {
            var document = _documentRepo.FirstOrDefault(input.Id);
            var documentStream = System.IO.File.OpenRead(System.IO.Path.Combine(document.PhysicalPath, document.PhysicalName));

            EventBus.Default.Trigger(new DocumentDownloadEvent { Document = document });

            return new DownloadDocumentOutput { Item = ObjectMapper.Map<DocumentDto>(document), DocumentStream = documentStream };
        }

        [HttpPost(nameof(DeleteDocument))]
        public virtual DeleteDocumentOutput DeleteDocument(DeleteDocumentInput input)
        {
            var document = _documentRepo.FirstOrDefault(input.Id);

            if (document == null)
            {
                throw new UserFriendlyException("文档无效");
            }

            _documentRepo.Delete(document);

            EventBus.Default.Trigger(new DocumentDeleteEvent { Document = document });

            return new DeleteDocumentOutput();
        }

        [HttpPost(nameof(SearchDocumentFolder))]
        public virtual SearchDocumentFolderOutput SearchDocumentFolder(SearchDocumentFolderInput input)
        {
            var folder = _documentFolderRepo.GetAll().ToList().FirstOrDefault() ??
                         _documentFolderRepo.Insert(new DocumentFolder { Name = "共享文档", ParentId = null, Level = 0 });

            var result = ObjectMapper.Map<List<DocumentFolderDto>>(new List<DocumentFolder> { folder });

            return new SearchDocumentFolderOutput { Items = result };
        }

        [HttpPost(nameof(SaveDocumentFolder))]
        public virtual SaveDocumentFolderOutput SaveDocumentFolder(SaveDocumentFolderInput input)
        {
            input.Item.Name = input.Item.Name.Trim();

            if (input.Item.Id <= 0)
            {
                if (!input.Item.ParentId.HasValue)
                {
                    throw new UserFriendlyException("创建目录发生错误，上级目录无效");
                }

                var parent = _documentFolderRepo.Get(input.Item.ParentId.Value);

                if (parent.Level >= 8)
                {
                    throw new UserFriendlyException("最多只能创建 8 级目录");
                }

                var folder = _documentFolderRepo.Insert(new DocumentFolder { Parent = parent, Name = input.Item.Name, Level = parent.Level + 1 });

                return new SaveDocumentFolderOutput { Item = ObjectMapper.Map<DocumentFolderDto>(folder) };
            }

            var exist = _documentFolderRepo.Get(input.Item.Id);

            exist.Name = input.Item.Name;

            return new SaveDocumentFolderOutput { Item = ObjectMapper.Map<DocumentFolderDto>(exist) };
        }

        [HttpPost(nameof(DeleteDocumentFolder))]
        public virtual DeleteDocumentFolderOutput DeleteDocumentFolder(DeleteDocumentFolderInput input)
        {
            var folder = _documentFolderRepo.FirstOrDefault(input.Id);

            if (folder == null)
            {
                throw new UserFriendlyException("目录无效");
            }

            var documents = _documentRepo.GetAll().Where(p => p.FolderId == folder.Id).ToList();

            _documentRepo.Delete(documents);
            _documentFolderRepo.Delete(folder);

            return new DeleteDocumentFolderOutput();
        }
    }
}

